<template>
  <div class="avatar-container">
    <!-- 提示列表 -->
    <div class="tips-list">
      <div class="tip-item" v-for="(tip, index) in tips" :key="index" @click="handleTipClick(tip)">
        {{ tip }}
      </div>
    </div>
    <!-- 虚拟人 -->
    <div ref="avatarWrapper" class="avatar-wrapper"></div>
    <!-- 播放遮罩层 -->
    <div v-if="showPlayMask" class="play-mask" @click="handleResume">
      <div class="play-button">
        <span>点击开始体验</span>
      </div>
    </div>
    <!-- 录音状态 -->
    <div v-if="isRecording" class="recording-indicator">
      <div class="recording-wave"></div>
      <span>实时通话中...</span>
    </div>
    <div class="chat-container-wrapper">
      <!-- 聊天消息 -->
      <div class="chat-container">
        <div class="chat-messages" ref="chatMessages" @click="handleChatContainerClick">
          <div
            v-for="(msg, index) in messages"
            :key="index"
            :class="['message', msg.type === 'user' ? 'message-right' : 'message-left']"
          >
            <img
              :src="
                msg.type === 'user'
                  ? 'https://img.qffssd.com/novel/img/cosmetic/user.png'
                  : 'https://img.qffssd.com/novel/img/cosmetic/avatar.png'
              "
              class="avatar"
            />
            <div class="message-content" v-html="msg.text"></div>
          </div>
        </div>
      </div>
      <!-- 控制面板 -->
      <div class="control-panel">
        <input
          v-model="inputText"
          type="text"
          placeholder="请输入文字..."
          @keyup.enter="sendText"
        />
        <button @click="sendText">发送</button>
        <div
          class="record-button"
          :class="{ recording: isRecording }"
          @touchstart.prevent="startRecord"
          @touchend.prevent="stopRecord"
          @mousedown.prevent="startRecord"
          @mouseup.prevent="stopRecord"
          @mouseleave.prevent="stopRecord"
        >
          <i class="microphone-icon"></i>
        </div>
      </div>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, onMounted, onUnmounted } from 'vue'
import AvatarPlatform, { PlayerEvents, SDKEvents } from './avatar-sdk-web_3.1.2.1002/index.js'
import { avatarConfig } from './config'

interface InitResponse {
  [key: string]: unknown
}

interface ErrorType {
  message: string
  code?: number
  [key: string]: unknown
}

interface Message {
  type: 'user' | 'avatar'
  text: string
}

const avatarWrapper = ref<HTMLDivElement>()
const inputText = ref('')
let avatarPlatform: AvatarPlatform | null = null

// 添加录音状态
const isRecording = ref(false)

// 添加消息列表
const messages = ref<Message[]>([])
const chatMessages = ref<HTMLElement>()

// 添加录音配置
const audioConfig = ref({
  nlp: true, // 是否启用语义理解
  fullDuplex: true, // 是否使用全双工模式
  singleSeconds: 20, // 单轮模式下的自动停止时间
})

// 添加播放遮罩层状态
const showPlayMask = ref(false)

// 添加提示文字列表
const tips = ['脸上有痘痘怎么办', '如何解决皮肤敏感', '怎么解决皮肤衰老', '皮肤缺水怎么办']

// 添加提示点击处理函数
const handleTipClick = async (text: string) => {
  inputText.value = text
  await sendText() // 直接发送文本
}

// 添加恢复播放函数
const handleResume = () => {
  if (!avatarPlatform) return
  avatarPlatform.player?.resume()
  showPlayMask.value = false
}

// 初始化虚拟人平台
const initAvatarPlatform = async () => {
  try {
    // 创建实例
    avatarPlatform = new AvatarPlatform()

    // 设置事件监听
    setupEventListeners()

    // 设置API信息
    avatarPlatform.setApiInfo({
      appId: avatarConfig.appId,
      apiKey: avatarConfig.apiKey,
      apiSecret: avatarConfig.apiSecret,
      sceneId: avatarConfig.serviceId,
      serverUrl: avatarConfig.tdpUrl,
    })

    // 设置全局参数
    avatarPlatform.setGlobalParams({
      stream: {
        protocol: 'xrtc',
      },
      avatar: {
        avatar_id: avatarConfig.avatarId,
        width: 720,
        height: 1280,
        mask_region: '[0, 0, 1080, 1920]',
        scale: 0.9,
        move_h: 0,
        move_v: 0,
        audio_format: 1,
      },
      background: {
        enabled: true,
        type: 'res_key',
        data: '22SLM2teIw+aqR6Xsm2JbH6Ng310kDam2NiCY/RQ9n6dw47gMO+7gGUJfWWfkqD3yAhsQSMoU70qevrgJlcCW7CpmGwtGvFCc4FAj6MwSXqlM5d2SWiBvcYQFVc5ms0v2vNpIVpLexi6IsWRcXm6dljXOegc8n4KjZTYn+P7cWJ+xftEsPfBGEZ3XXEUBmFw0HHwNL6xZG5Seg6ABTEl8orZQwvs148BR1PRcb11HRFjlKT+iV3+fswpzFou/qoqwnIQV2df6MFZJ+g6Ul0VrbmCiIzASjgskB1YJpR93JfLrbbLeLD9ZSacLA32FaoGbGzn0gcE+Dv4CLPwSE6IIgkF+tux4d88hmvOisdUzSc=',
      },
      tts: {
        vcn: avatarConfig.vcn,
      },
    })

    // 拟人
    await avatarPlatform.start({
      wrapper: avatarWrapper.value,
    })

    // 创建或获取 player 实例
    const player = avatarPlatform.player || avatarPlatform.createPlayer()
    player
      ?.on(PlayerEvents.play, () => {
        console.log('sdk event: player play')
      })
      .on(PlayerEvents.waiting, () => {
        console.log('sdk event: player waiting')
      })
      .on(PlayerEvents.playing, () => {
        console.log('sdk event: player playing')
      })
      .on(PlayerEvents.playNotAllowed, () => {
        console.log('sdk event: play not allowed, muted play')
        showPlayMask.value = true
      })

    console.log('虚拟人初始化成功')
  } catch (error) {
    console.error('虚拟人初始化失败:', error)
  }
}

// 设置事件监听
const setupEventListeners = () => {
  avatarPlatform
    .on(SDKEvents.connected, (initResp: InitResponse) => {
      console.log('连接成功', initResp)
    })
    .on(SDKEvents.stream_start, () => {
      console.log('流开始')
    })
    .on(SDKEvents.disconnected, (err: ErrorType) => {
      console.log('连接断开', err)
    })
    .on(SDKEvents.error, (error: ErrorType) => {
      console.error('错误:', error)
    })
    .on(SDKEvents.asr, (asrData: any) => {
      console.log('语音识别(ASR)结果:', asrData)
      // ASR 结果只打印日志，不添加到消息列表
    })
    .on(SDKEvents.nlp, (nlpData: any) => {
      console.log('语义理解(NLP)结果:', nlpData)
      if (nlpData?.answer?.text) {
        // 处理消息中的图片标记
        const text = nlpData.answer.text.replace(/\[\[img=(.*?)\]\]/g, (match: string, url: string) => {
          const nUrl = url.split(',')[0]
          const id = url.split(',')[1]?.replace('id=', '') // 提取id数字
          console.log('处理图片:', { nUrl, id }) // 调试日志
          return `<img src="${nUrl}" data-id="${id}" class="chat-image" style="max-width: 200px; border-radius: 8px; cursor: pointer;" />`
        })

        // 添加虚拟人消息
        messages.value.push({
          type: 'avatar',
          text: text,
        })

        // 滚动到底部
        setTimeout(() => {
          if (chatMessages.value) {
            chatMessages.value.scrollTop = chatMessages.value.scrollHeight
          }
        }, 100)
      }
    })
    .on(SDKEvents.recorder_start, () => {
      console.log('录音器开始工作')
    })
    .on(SDKEvents.recorder_stop, () => {
      console.log('录音器停止工作')
    })
    .on(SDKEvents.tts_duration, (data: any) => {
      console.log('TTS 时长:', data)
    })
    .on(SDKEvents.frame_start, (data: any) => {
      console.log('帧开始:', data)
    })
    .on(SDKEvents.frame_stop, (data: any) => {
      console.log('帧结束:', data)
    })
}

// 发送文本
const sendText = async () => {
  if (!inputText.value) return
  try {
    // 添加用户消息
    messages.value.push({
      type: 'user',
      text: inputText.value,
    })

    await avatarPlatform?.writeText(inputText.value, {
      nlp: true,
    })
    inputText.value = ''

    // 滚动到底部
    setTimeout(() => {
      if (chatMessages.value) {
        chatMessages.value.scrollTop = chatMessages.value.scrollHeight
      }
    }, 100)
  } catch (error) {
    console.error('发送文本失败:', error)
  }
}

// 开始录音
const startRecord = async () => {
  if (!avatarPlatform) {
    console.error('SDK 未初始化')
    return
  }

  try {
    console.log('开始请求麦克风权限...')
    await navigator.mediaDevices?.getUserMedia({ audio: true })
    console.log('麦克风权限获取成功')

    // 检查录音器采样率是否正确
    if (avatarPlatform.recorder) {
      if (audioConfig.value.nlp && avatarPlatform.recorder.sampleRate !== 16000) {
        // 交互拾音只支持16k 16bit
        avatarPlatform.destroyRecorder()
      }
    }

    // 创建录音器
    if (!avatarPlatform.recorder) {
      avatarPlatform.createRecorder({
        sampleRate: 16000, // 交互必须使用 16k 采样率
      })
    }

    const recorder = avatarPlatform.recorder
    if (!recorder) {
      throw new Error('录音器创建失败')
    }

    isRecording.value = true
    console.log('录音状态:', isRecording.value)
    // recognizedText.value = '' // 清空上一次的识别结果

    // 开始录音
    recorder.startRecord(
      audioConfig.value.fullDuplex ? 0 : audioConfig.value.singleSeconds * 1000,
      () => {
        console.log('录音自动停止')
        isRecording.value = false
      },
      {
        nlp: audioConfig.value.nlp,
      },
    )
    console.log('录音开始...')
  } catch (error) {
    console.error('开始录音失败:', error)
    isRecording.value = false
  }
}

// 停止录音
const stopRecord = () => {
  if (!avatarPlatform) {
    console.error('SDK 未初始化')
    return
  }

  console.log('准备停止录音...')
  if (!isRecording.value) {
    console.log('录音未开始，不需要停止')
    return
  }

  try {
    const recorder = avatarPlatform.recorder
    if (recorder) {
      console.log('正在停止录音...')
      recorder.stopRecord()
      console.log('录音已停止')
    }
  } catch (error) {
    console.error('停止录音失败:', error)
  } finally {
    isRecording.value = false
  }
}

// 添加停止虚拟人函数
const stopAvatar = () => {
  if (!avatarPlatform) {
    console.error('SDK 未初始化')
    return
  }
  avatarPlatform.stop()
}

onMounted(async () => {
  initAvatarPlatform()
})

// 组件卸载时清理
onUnmounted(() => {
  if (avatarPlatform) {
    avatarPlatform.stop()
    avatarPlatform.destroy()
  }
})

// 在 setup 中添加事件委托处理函数
const handleChatContainerClick = (e: Event) => {
  const target = e.target as HTMLElement
  if (target.tagName === 'IMG' && target.classList.contains('chat-image')) {
    const id = target.getAttribute('data-id')
    console.log('图片被点击，元素:', target)
    if (id) {
      console.log('图片被点击，ID:', id)
      if (window.wx?.miniProgram) {
        window.wx.miniProgram.postMessage({ data: { id: Number(id) } })
      }
    }
  }
}

// 添加类型声明
declare global {
  interface Window {
    handleChatImage: (id: number) => void
    wx?: {
      miniProgram?: {
        postMessage: (message: { data: any }) => void
      }
    }
  }
}
</script>
<style>
#xvideo div {
  width: 100% !important;
  height: 100% !important;
  transform: translate3d(-25%, -25%, 0px) scale(1, 1) !important;
}
</style>
<style scoped>
.avatar-container {
  width: 100%;
  height: 100%;
  display: flex;
  flex-direction: column;
  position: relative;
}

.avatar-wrapper {
  flex: 1;
  width: 100vw;
  height: 100vh;
  background-color: #000;
  position: relative;
}

.control-panel {
  width: 100%;
  padding: 0 16px;
  display: flex;
  gap: 8px;
}

.control-panel input {
  flex: 1;
  height: 30px;
  padding: 0 12px;
  border: 1px solid #ddd;
  border-radius: 15px;
  font-size: 12px;
  background: transparent;
  color: #fff;
  outline: none;
}

.control-panel input::placeholder {
  color: #fff;
  font-size: 12px;
}

.control-panel button {
  height: 30px;
  padding: 0 16px;
  border: none;
  border-radius: 4px;
  background-color: #14141452;
  color: #fff;
  font-size: 12px;
  cursor: pointer;
}

.control-panel button:active {
  opacity: 0.8;
}

.record-button {
  height: 30px;
  width: 30px;
  padding: 0;
  border: none;
  border-radius: 4px;
  background-color: #14141452;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  user-select: none;
  transition: all 0.2s;
}

.record-button:active,
.record-button.recording {
  background-color: #ff4d4f;
}

.microphone-icon {
  width: 20px;
  height: 20px;
  background-image: url('');
  background-repeat: no-repeat;
  background-position: center;
  background-size: contain;
}

.qr-code {
  position: absolute;
  right: 20px;
  top: 20px;
  background: rgba(255, 255, 255, 0.9);
  padding: 15px;
  border-radius: 12px;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
  text-align: center;
  backdrop-filter: blur(8px);
}

.qr-code img {
  width: 150px;
  height: 150px;
  border-radius: 8px;
}

.qr-code p {
  margin: 10px 0 0;
  font-size: 14px;
  color: #333;
  font-weight: 500;
}

.recording-indicator {
  position: fixed;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  background: rgba(0, 0, 0, 0.7);
  border-radius: 40px;
  color: white;
  display: flex;
  align-items: center;
  gap: 12px;
  z-index: 1000;
}

.recording-wave {
  width: 20px;
  height: 20px;
  background: #ff4d4f;
  border-radius: 50%;
  animation: wave 1s infinite ease-in-out;
}

@keyframes wave {
  0% {
    transform: scale(0.8);
    opacity: 0.5;
  }
  50% {
    transform: scale(1.2);
    opacity: 1;
  }
  100% {
    transform: scale(0.8);
    opacity: 0.5;
  }
}

.chat-container-wrapper {
  position: absolute;
  bottom: 20px;
  left: 0;
  width: 100vw;
  background: transparent;
}
.chat-container {
  padding: 0 16px;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  height: 300px;
  margin-top: 0;
}

.chat-messages {
  flex: 1;
  overflow-y: auto;
  height: 100%;
  -ms-overflow-style: none; /* IE and Edge */
  scrollbar-width: none; /* Firefox */
}

/* 隐藏 Webkit 浏览器的滚动条 */
.chat-messages::-webkit-scrollbar {
  display: none;
}

.message {
  display: flex;
  align-items: flex-start;
  margin-bottom: 4px;
  gap: 8px;
}

.message-left {
  flex-direction: row;
}

.message-right {
  flex-direction: row-reverse;
}

.avatar {
  width: 20px;
  height: 20px;
  border-radius: 20px;
  background: #fff;
  padding: 4px;
}

.message-content {
  max-width: 70%;
  padding: 4px 16px;
  border-radius: 5px;
  font-size: 12px;
  line-height: 1.5;
  word-break: break-word;
  position: relative;
}

.message-left .message-content {
  background: #14141452;
  color: #fff;
  margin-left: 6px;
}

.message-right .message-content {
  background: #14141452;
  color: #fff;
  margin-right: 6px;
}

.message-left .message-content::before {
  content: '';
  position: absolute;
  top: 8px;
  left: -3px;
  width: 6px;
  height: 6px;
  background: inherit;
  transform: rotate(45deg);
}

.message-right .message-content::before {
  content: '';
  position: absolute;
  top: 8px;
  right: -3px;
  width: 6px;
  height: 6px;
  background: inherit;
  transform: rotate(45deg);
}

/* 添加播放遮罩层样式 */
.play-mask {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background: rgba(0, 0, 0, 0.6);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 1000;
  cursor: pointer;
}

.play-button {
  padding: 16px 32px;
  background: #1890ff;
  border-radius: 24px;
  color: white;
  font-size: 16px;
  transition: all 0.3s;
}

.play-button:hover {
  background: #40a9ff;
  transform: scale(1.05);
}

.tips-list {
  position: absolute;
  left: 20px;
  top: 20px;
  z-index: 10;
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.tip-item {
  background: #d6d6df5c;
  padding: 2px 10px;
  border-radius: 20px;
  font-size: 13px;
  color: #dedede;
  cursor: pointer;
  border: 1px solid #fff;
}

.tip-item:hover {
  transform: translateX(5px);
  background: transparent;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
}
</style>
